package com.learning.crpc.consummer;

import com.learning.crpc.model.CrpcRequest;
import com.learning.crpc.protocol.NettyCodec;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: diy_rpc
 * @description:
 * @author: CaoYong
 * @create: 2021-07-01 17:46
 **/
public class NettyConsumerClient {

    public static ConcurrentHashMap<InetSocketAddress, CrpcConnection> connectionInfo = new ConcurrentHashMap<>();

    public static CrpcConnection connect(String host, int port) throws Exception {
        InetSocketAddress inetSocketAddress = new InetSocketAddress(host, port);

        CrpcConnection existCrpcConnection = connectionInfo.get(inetSocketAddress);
        if (existCrpcConnection != null) {
            return existCrpcConnection;
        }

        NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();

        bootstrap.group(nioEventLoopGroup);
        bootstrap.channel(NioSocketChannel.class);

        bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                socketChannel.pipeline().addLast(new NettyCodec(CrpcRequest.class));
                socketChannel.pipeline().addLast(new NettyConsumerHandler());
            }
        });

        Channel channel = bootstrap.connect(inetSocketAddress).await().channel();
        CrpcConnection crpcConnection = new CrpcConnection(channel);

        if(connectionInfo.putIfAbsent(inetSocketAddress, crpcConnection) != null) {
            channel.closeFuture();
            return connectionInfo.get(inetSocketAddress);
        }

        return crpcConnection;
    }
}
